package com.campus.secondhand.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.secondhand.common.Result;
import com.campus.secondhand.entity.School;
import com.campus.secondhand.entity.User;
import com.campus.secondhand.mapper.UserMapper;
import com.campus.secondhand.model.dto.LoginDTO;
import com.campus.secondhand.model.dto.RegisterDTO;
import com.campus.secondhand.model.dto.UpdatePasswordDTO;
import com.campus.secondhand.model.dto.UserInfoDTO;
import com.campus.secondhand.model.dto.ResetPasswordDTO;
import com.campus.secondhand.model.vo.UserInfoVO;
import com.campus.secondhand.model.vo.UserLoginVO;
import com.campus.secondhand.security.JwtTokenProvider;
import com.campus.secondhand.service.SchoolService;
import com.campus.secondhand.service.UserService;
import com.campus.secondhand.service.VerificationCodeService;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 用户服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;
    private final JwtTokenProvider jwtTokenProvider;
    private final VerificationCodeService verificationCodeService;
    private final SchoolService schoolService;
    private final RedisTemplate<String, Object> redisTemplate;

    // Redis缓存键常量
    private static final String CACHE_USER_PREFIX = "user:";
    private static final String CACHE_USER_INFO_PREFIX = "user:info:";
    private static final String CACHE_USER_USERNAME_PREFIX = "user:username:";
    private static final long CACHE_USER_EXPIRE = 12; // 缓存过期时间，单位小时

    @Override
    public Result<UserLoginVO> login(LoginDTO loginDTO) {
        User user;
        if (loginDTO.getUsername().contains("@")) {
            // 使用邮箱登录
            user = this.lambdaQuery()
                    .eq(User::getEmail, loginDTO.getUsername())
                    .eq(User::getStatus, 1)
                    .one();
        } else {
            // 使用用户名登录
            user = this.lambdaQuery()
                    .eq(User::getUsername, loginDTO.getUsername())
                    .eq(User::getStatus, 1)
                    .one();
        }

        if (user == null) {
            return Result.error(401, "用户不存在");
        }

        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            return Result.error(401, "密码错误");
        }

        // 生成JWT令牌
        org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(
                user.getUsername(), user.getPassword(), java.util.Collections.emptyList());

        String token = jwtTokenProvider.generateToken(userDetails);

        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .role("user")
                .token(token)
                .build();

        return Result.success(userLoginVO, "登录成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<User> register(RegisterDTO registerDTO) {

        // // 验证手机验证码
        // if (!verificationCodeService.verifyCode(registerDTO.getPhone(),
        // registerDTO.getCode(), "register")) {
        // return Result.error(400, "验证码错误或已过期");
        // }

        // 检查用户名是否已存在
        LambdaQueryWrapper<User> usernameQuery = new LambdaQueryWrapper<>();
        usernameQuery.eq(User::getUsername, registerDTO.getUsername());
        long usernameCount = this.count(usernameQuery);
        if (usernameCount > 0) {
            return Result.error(400, "用户名已存在");
        }

        // 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        // 数据库中密码加密
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setNickname(registerDTO.getNickname());
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setSchoolId(Long.valueOf(registerDTO.getSchool()));
        user.setCredibility(100);
        user.setStatus(1);
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());

        // 保存用户
        this.save(user);

        // 更新学校成员数量
        Long schoolId = Long.valueOf(registerDTO.getSchool());
        School school = schoolService.getById(schoolId);
        if (school != null) {
            // 更新学校成员数量
            school.setMemberCount(school.getMemberCount() == null ? 1 : school.getMemberCount() + 1);
            schoolService.updateById(school);
            log.info("用户注册成功，已将学校 {} 的成员数量更新为 {}", school.getName(), school.getMemberCount());
        } else {
            log.warn("用户注册成功，但未找到指定的学校ID: {}", schoolId);
        }

        // 不返回密码
        user.setPassword(null);
        return Result.success(user, "注册成功");
    }

    @Override
    public Result<UserInfoVO> getUserInfo(Long id) {
        // 尝试从缓存获取
        String cacheKey = CACHE_USER_INFO_PREFIX + id;
        Object cachedUserInfo = redisTemplate.opsForValue().get(cacheKey);
        if (cachedUserInfo != null) {
            return Result.success((UserInfoVO) cachedUserInfo, "获取成功(缓存)");
        }

        User user = this.getById(id);
        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        String schoolName = null;
        if (user.getSchoolId() != null) {
            Result<School> schoolResult = schoolService.getSchoolById(user.getSchoolId());
            if (schoolResult.getCode() == 200 && schoolResult.getData() != null) {
                schoolName = schoolResult.getData().getName();
            } else {
                log.warn("无法获取用户ID: {} 的学校信息, 学校ID: {}", id, user.getSchoolId());
            }
        }

        // 假设这里可以获取学校、专业等信息，实际中可能需要关联查询
        UserInfoVO userInfoVO = UserInfoVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .role("user") // TODO: 角色信息应该从用户实际角色字段获取
                .school(schoolName) // 使用获取到的学校名称
                .major(user.getMajor()) // 假设User实体有major字段
                .bio(user.getIntroduction()) // User实体中使用introduction字段对应UserInfoVO.bio
                .credibility(user.getCredibility())
                .build();

        // 保存到缓存
        redisTemplate.opsForValue().set(cacheKey, userInfoVO, CACHE_USER_EXPIRE, TimeUnit.HOURS);

        return Result.success(userInfoVO, "获取成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> updateUserInfo(Long id, UserInfoDTO userInfoDTO) {
        User user = this.getById(id);
        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        Long oldSchoolId = user.getSchoolId();
        String oldSchoolName = null;
        if (oldSchoolId != null) {
            School os = schoolService.getById(oldSchoolId);
            if (os != null) {
                oldSchoolName = os.getName();
            }
        }

        // 处理学校变更
        if (StrUtil.isNotBlank(userInfoDTO.getSchool()) && !userInfoDTO.getSchool().equals(oldSchoolName)) {
            School newSchool = schoolService.lambdaQuery().eq(School::getName, userInfoDTO.getSchool()).one();
            if (newSchool != null) {
                // 旧学校成员数量-1
                    if (oldSchoolId != null) {
                    School oldSchool = schoolService.getById(oldSchoolId);
                    if (oldSchool != null && oldSchool.getMemberCount() != null && oldSchool.getMemberCount() > 0) {
                        oldSchool.setMemberCount(oldSchool.getMemberCount() - 1);
                        schoolService.updateById(oldSchool);
                    }
                    }

                // 新学校成员数量+1
                    newSchool.setMemberCount(newSchool.getMemberCount() == null ? 1 : newSchool.getMemberCount() + 1);
                    schoolService.updateById(newSchool);

                // 更新用户的学校ID
                user.setSchoolId(newSchool.getId());
                }
        }

        // 更新用户信息
        if (StrUtil.isNotBlank(userInfoDTO.getNickname())) {
            user.setNickname(userInfoDTO.getNickname());
        }
        if (StrUtil.isNotBlank(userInfoDTO.getMajor())) {
            user.setMajor(userInfoDTO.getMajor());
        }
        if (StrUtil.isNotBlank(userInfoDTO.getBio())) {
            user.setIntroduction(userInfoDTO.getBio());
        }

        user.setUpdatedAt(LocalDateTime.now());
        boolean success = updateById(user);

        if (success) {
            // 清除相关缓存
            clearUserCache(id);
            return Result.success(null, "更新成功");
        } else {
            return Result.error("更新失败");
        }
    }

    /**
     * 修改密码（已登录用户）
     * 需要验证旧密码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> updatePassword(Long id, UpdatePasswordDTO updatePasswordDTO) {
        User user = this.getById(id);
        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        // 验证原密码
        if (!passwordEncoder.matches(updatePasswordDTO.getOldPassword(), user.getPassword())) {
            return Result.error(400, "原密码错误");
        }

        // 更新密码
        user.setPassword(passwordEncoder.encode(updatePasswordDTO.getNewPassword()));
        user.setUpdatedAt(LocalDateTime.now());
        boolean success = updateById(user);

        if (success) {
            // 清除相关缓存
            clearUserCache(id);
            return Result.success(null, "密码更新成功");
        } else {
            return Result.error("密码更新失败");
        }
    }

    @Override
    public Result<User> getByUsername(String username) {
        if (StrUtil.isBlank(username)) {
            return Result.error(400, "用户名不能为空");
        }

        // 尝试从缓存获取
        String cacheKey = CACHE_USER_USERNAME_PREFIX + username;
        Object cachedUser = redisTemplate.opsForValue().get(cacheKey);
        if (cachedUser != null) {
            return Result.success((User) cachedUser, "获取成功(缓存)");
        }

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = getOne(queryWrapper);

        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        // 不返回密码
        user.setPassword(null);

        // 保存到缓存
        redisTemplate.opsForValue().set(cacheKey, user, CACHE_USER_EXPIRE, TimeUnit.HOURS);

        return Result.success(user, "获取成功");
    }

    /**
     * 重置密码（忘记密码）
     * 需要验证手机验证码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> resetPassword(ResetPasswordDTO resetPasswordDTO) {
        // // 验证手机验证码
        // if (!verificationCodeService.verifyCode(resetPasswordDTO.getPhone(),
        // resetPasswordDTO.getCode(), "reset")) {
        // return Result.error(400, "验证码错误或已过期");
        // }

        // 根据手机号查询用户
        User user = this.lambdaQuery()
                .eq(User::getPhone, resetPasswordDTO.getPhone())
                .eq(User::getStatus, 1)
                .one();

        if (user == null) {
            return Result.error(404, "该手机号未注册");
        }

        // 更新密码
        user.setPassword(passwordEncoder.encode(resetPasswordDTO.getNewPassword()));
        user.setUpdatedAt(LocalDateTime.now());

        boolean result = this.updateById(user);
        return result ? Result.success(null, "密码重置成功") : Result.error("密码重置失败");
    }

    /**
     * 根据用户ID获取用户实体
     */
    @Override
    public User getUserById(Long userId) {
        if (userId == null) {
            return null;
        }

        // 尝试从缓存获取
        String cacheKey = CACHE_USER_PREFIX + userId;
        Object cachedUser = redisTemplate.opsForValue().get(cacheKey);
        if (cachedUser != null) {
            return (User) cachedUser;
        }

        User user = this.getById(userId);

        // 保存到缓存
        if (user != null) {
            redisTemplate.opsForValue().set(cacheKey, user, CACHE_USER_EXPIRE, TimeUnit.HOURS);
        }

        return user;
    }

    /**
     * 清除用户相关缓存
     * 
     * @param userId 用户ID
     */
    private void clearUserCache(Long userId) {
        if (userId == null) {
            return;
        }

        log.info("清除用户缓存: {}", userId);
        String userKey = CACHE_USER_PREFIX + userId;
        String userInfoKey = CACHE_USER_INFO_PREFIX + userId;

        redisTemplate.delete(userKey);
        redisTemplate.delete(userInfoKey);

        // 尝试获取用户名，如果可以获取则清除用户名缓存
        User user = this.getById(userId);
        if (user != null && StrUtil.isNotBlank(user.getUsername())) {
            String usernameKey = CACHE_USER_USERNAME_PREFIX + user.getUsername();
            redisTemplate.delete(usernameKey);
        }
    }
}